feat(plays): Updated add BMR and TDEE calculator#1664
feat(plays): Updated add BMR and TDEE calculator#1664aniketmishra-0 wants to merge 3 commits intoreactplay:mainfrom
Conversation
❌ Deploy Preview for reactplayio failed. Why did it fail? →
|
There was a problem hiding this comment.
Hey! contributor, thank you for opening a Pull Request 🎉.
@reactplay/maintainers will review your submission soon and give you helpful feedback.
If you're interested in continuing your contributions to open source and want to be a part of a welcoming and fantastic community, we invite you to join our ReactPlay Discord Community.
Show your support by starring ⭐ this repository. Thank you and we appreciate your contribution to open source!
Stale Marking : After 30 days of inactivity this issue/PR will be marked as stale issue/PR and it will be closed and locked in 7 days if no further activity occurs.
There was a problem hiding this comment.
Pull request overview
Adds a new “BMR & TDEE Calculator” play to the ReactPlay plays catalog, providing an interactive calculator for BMR (Mifflin–St Jeor) and TDEE with metric/imperial input support and results display.
Changes:
- Introduces a new
BmrTdeeCalculatorReact play with inputs, unit toggles, and computed result cards (BMR/TDEE/deficit/surplus). - Adds scoped styling and a cover image for the play.
- Registers the play export in
src/plays/index.jsand adds play documentation.
Reviewed changes
Copilot reviewed 6 out of 7 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
src/plays/index.js |
Registers the new play via an export. |
src/plays/bmr-tdee-calculator/BmrTdeeCalculator.jsx |
Implements the calculator UI and BMR/TDEE computation logic. |
src/plays/bmr-tdee-calculator/styles.css |
Adds play-specific styling and result animations. |
src/plays/bmr-tdee-calculator/Readme.md |
Documents formulas, usage, and references for the play. |
src/plays/bmr-tdee-calculator/cover.svg |
Adds the play cover asset. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| <button | ||
| className={`bmr-tdee-toggle-btn ${unit === 'metric' ? 'active' : ''}`} | ||
| onClick={() => setUnit('metric')} | ||
| type="button" | ||
| > | ||
| Metric (kg/cm) | ||
| </button> | ||
| <button | ||
| className={`bmr-tdee-toggle-btn ${unit === 'imperial' ? 'active' : ''}`} | ||
| onClick={() => setUnit('imperial')} | ||
| type="button" | ||
| > | ||
| Imperial (lbs/in) | ||
| </button> |
There was a problem hiding this comment.
Switching the unit system only changes the labels; any existing weight/height values remain unchanged but are interpreted in the new unit on the next calculation (e.g., "70" becomes 70 lbs instead of 70 kg). To avoid incorrect results, either convert existing inputs when toggling units or clear the affected fields/results on unit change.
| <label className="bmr-tdee-label">Unit System</label> | ||
| <div className="bmr-tdee-toggle-group"> | ||
| <button | ||
| className={`bmr-tdee-toggle-btn ${unit === 'metric' ? 'active' : ''}`} | ||
| onClick={() => setUnit('metric')} | ||
| type="button" | ||
| > | ||
| Metric (kg/cm) | ||
| </button> | ||
| <button | ||
| className={`bmr-tdee-toggle-btn ${unit === 'imperial' ? 'active' : ''}`} | ||
| onClick={() => setUnit('imperial')} | ||
| type="button" | ||
| > | ||
| Imperial (lbs/in) | ||
| </button> | ||
| </div> | ||
| </div> | ||
|
|
||
| {/* Gender */} | ||
| <div className="bmr-tdee-field"> | ||
| <label className="bmr-tdee-label">Gender</label> | ||
| <div className="bmr-tdee-toggle-group"> | ||
| <button | ||
| className={`bmr-tdee-toggle-btn ${gender === 'male' ? 'active' : ''}`} | ||
| onClick={() => setGender('male')} | ||
| type="button" | ||
| > | ||
| ♂ Male | ||
| </button> | ||
| <button | ||
| className={`bmr-tdee-toggle-btn ${gender === 'female' ? 'active' : ''}`} | ||
| onClick={() => setGender('female')} | ||
| type="button" | ||
| > | ||
| ♀ Female | ||
| </button> |
There was a problem hiding this comment.
The unit and gender selectors are implemented as toggle buttons but don’t expose pressed state to assistive tech. Add aria-pressed (and consider role="group"/aria-label on the container) so screen readers can understand which option is selected.
| animation: bmrFadeIn 0.4s ease; | ||
| } | ||
|
|
||
| @keyframes bmrFadeIn { |
There was a problem hiding this comment.
The animation name bmrFadeIn is global and not namespaced like the rest of this play’s CSS. Rename the keyframes (and the animation: reference) to include the bmr-tdee- prefix to reduce the chance of collisions with other plays’ styles.
| animation: bmrFadeIn 0.4s ease; | |
| } | |
| @keyframes bmrFadeIn { | |
| animation: bmr-tdee-fade-in 0.4s ease; | |
| } | |
| @keyframes bmr-tdee-fade-in { |
| export { default as BmrTdeeCalculator } from 'plays/bmr-tdee-calculator/BmrTdeeCalculator'; | ||
| export { default as CodeEditor } from 'plays/code-editor/CodeEditor'; | ||
| export { default as CdTimerComp } from 'plays/date-time-counter/CdTimerComp'; | ||
| export { default as AnalogClock } from 'plays/analog-clock/AnalogClock'; | ||
| export { default as RegistrationForm } from 'plays/registration-form/RegistrationForm'; |
There was a problem hiding this comment.
All export statements in this file are indented with a leading space while the rest of the codebase generally keeps top-level exports unindented. This can create noisy diffs and may fail formatting/lint rules; consider running the formatter or removing the leading whitespace.
| let weightKg = parseFloat(weight); | ||
| let heightCm = parseFloat(height); | ||
|
|
||
| if (!ageNum || !weightKg || !heightCm) { |
There was a problem hiding this comment.
calculateBMR returns early on invalid/empty input without clearing any prior result, which can leave stale results visible after the user edits/clears fields. Consider setting result back to null (and optionally surfacing a small validation message or disabling the Calculate button until inputs are valid) when inputs are incomplete/invalid.
| if (!ageNum || !weightKg || !heightCm) { | |
| if (!ageNum || !weightKg || !heightCm) { | |
| setResult(null); |
Add a new play that calculates Basal Metabolic Rate and Total Daily Energy Expenditure using the Mifflin-St Jeor Equation. Features include metric and imperial unit support, five activity levels, weight loss and gain calorie targets, responsive design, and smooth result animations. Closes reactplay#1660
c73dca8 to
616ef56
Compare
priyankarpal
left a comment
There was a problem hiding this comment.
The Netlify deploy errored, with the following guidance provided:
Diagnosis
The build fails because src/plays/index.js contains an invalid export alias. The identifier Bmr-TdeeCalculator in the export statement is parsed as a subtraction expression, triggering the syntax error shown at line 856-line 860.
Solution
Rename the export alias so it uses a valid JavaScript identifier (e.g., camelCase or PascalCase with no hyphen). In src/plays/index.js, update the export and ensure any corresponding imports use the same name:
export { default as BmrTdeeCalculator } from 'plays/bmr-tdee-calculator';After committing this change (and updating any imports that referenced the old name), re-run the build.
The relevant error logs are:
Line 24: WARN deprecated @types/[email protected]: This is a stub types definition. dompurify provides its own type definitions, so you d
Line 25: WARN deprecated [email protected]: Please use eslint-config-love, instead.
Line 26: WARN deprecated [email protected]: This version is no longer supported. Please see https://eslint.org/version-support for other op
Line 27: Progress: resolved 30, reused 30, downloaded 0, added 0
Line 28: WARN deprecated @nhost/[email protected]: ⚠ DEPRECATED: This package is deprecated in favor of @nhost/nhost-js@^4.0.0. The new SDK i
Line 29: WARN deprecated [email protected]: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.
Line 30: WARN deprecated [email protected]: [email protected]
Line 31: Progress: resolved 113, reused 113, downloaded 0, added 0
Line 32: Progress: resolved 506, reused 471, downloaded 0, added 0
Line 33: Progress: resolved 1290, reused 1258, downloaded 0, added 0
Line 34: WARN 33 deprecated subdependencies found: @babel/[email protected], @babel/plugin-proposal-nullish-coale
Line 35: Progress: resolved 1790, reused 1758, downloaded 0, added 0
Line 36: Already up to date
Line 37: Progress: resolved 1790, reused 1758, downloaded 0, added 0, done
Line 38: > [email protected] prepare /opt/build/repo
Line 39: > husky install
Line 40: husky - Git hooks installed
Line 41: WARN Issues with peer dependencies found
Line 42: .
Line 43: ├─┬ json-graphql-parser 0.1.9
Line 44: │ └── ✕ unmet peer axios@^0.27.2: found 1.13.4
Line 844: WARNING : Wednesday, Feb 11, 2026: WARNING : Play not found locally : 25(25)
Line 845: INFO : Wednesday, Feb 11, 2026: INFO : Checking play locally: Soham Bhattacharya(soham-bhattacharya)
Line 846: WARNING : Wednesday, Feb 11, 2026: WARNING : Play not found locally : Soham Bhattacharya(soham-bhattacharya)
Line 847: INFO : Wednesday, Feb 11, 2026: INFO : Checking play locally: BMR & TDEE Calculator(bmr-tdee-calculator)
Line 848: INFO : Wednesday, Feb 11, 2026: INFO : Play found locally : bmr-tdee-calculator
Line 849: INFO : Wednesday, Feb 11, 2026: INFO : Checking play locally: Body Composition Calculator(body-composition-calculator)
Line 850: INFO : Wednesday, Feb 11, 2026: INFO : Play found locally : body-composition-calculator
Line 851: (node:2474) [DEP0176] DeprecationWarning: fs.F_OK is deprecated, use fs.constants.F_OK instead
Line 852: (Use node --trace-deprecation ... to show where the warning was created)
Line 853: Creating an optimized production build...
Line 854: �[31mFailed to compile.�[39m
Line 855: �[31m�[39m
Line 856: SyntaxError: /opt/build/repo/src/plays/index.js: Unexpected token, expected "," (115:24)
Line 857: �[0m �[90m 113 |�[39m �[36mexport�[39m { �[36mdefault�[39m �[36mas�[39m �[33mTextToSpeech�[39m } �[36mfrom�[39m �[32m'plays/tex
Line 858: �[90m 114 |�[39m �[36mexport�[39m { �[36mdefault�[39m �[36mas�[39m �[33mSimpleTodoApp�[39m } �[36mfrom�[39m �[32m'plays/simple
Line 859: �[31m�[1m>�[22m�[39m�[90m 115 |�[39m �[36mexport�[39m { �[36mdefault�[39m �[36mas�[39m �[33mBmr�[39m�[33m-�[39m�[33mTdeeCalcula
Line 860: �[90m |�[39m �[31m�[1m^�[22m�[39m
Line 861: �[90m 116 |�[39m �[36mexport�[39m { �[36mdefault�[39m �[36mas�[39m �[33mBodyCompositionCalculator�[39m } �[36mfrom�[39m �[32m'
Line 862: at parser.next ()
Line 863: at normalizeFile.next ()
Line 864: at run.next ()
Line 865: at transform.next ()
Line 866: Failed during stage 'building site': Build script returned non-zero exit code: 2
Line 867: �[91m�[1m�[22m�[39m
Line 868: �[91m�[1m"build.command" failed �[22m�[39m
Line 869: �[91m�[1m────────────────────────────────────────────────────────────────�[22m�[39m
Line 870:
Line 871: �[31m�[1mError message�[22m�[39m
Line 872: Command failed with exit code 1: npm run build
Line 873:
Line 874: �[31m�[1mError location�[22m�[39m
Line 875: In build.command from netlify.toml:
Line 876: npm run build
Line 877:
Line 878: �[31m�[1mResolved config�[22m�[39m
Line 879: build:
Line 880: command: npm run build
Line 881: commandOrigin: config
Line 882: environment:
Line 883: - CI
Line 884: - NODE_OPTIONS
Line 940: - VITE_SEARCH_APIHOST
Line 941: - VITE_SEARCH_APIKEY
Line 942: - VITE_SEARCH_URL
Line 943: - VITE_TUBETUNES_APIKEY
Line 944: - VITE_UMAMI_TRACK_ID
Line 945: - VITE_WEATHER_API_KEY
Line 946: publish: /opt/build/repo/build
Line 947: publishOrigin: config
Line 948: headers:
Line 949: - for: /*
values:
X-Frame-Options: DENY
headersOrigin: config
redirects:
- from: /*
status: 200
Line 950: Build failed due to a user error: Build script returned non-zero exit code: 2
Line 951: Failing build: Failed to build site
Line 952: Finished processing build request in 1m32.392s
Description
Closes #1660
A new play that calculates Basal Metabolic Rate (BMR) and Total Daily Energy Expenditure (TDEE) using the Mifflin-St Jeor Equation.
Features
Files Added
Screenshots
The calculator has two states:
Testing